import { IPSAppCodeList, IPSDEGrid, IPSDEGridColumn, IPSDEGridEditItem, IPSDEGridFieldColumn } from "@ibiz/dynamic-model-api";
import { IParam } from "../../interface";
import { SheetUtil, Util } from "../../utils";

/**
 * @description 虚拟表格服务
 * @export
 * @class AppVisualGridService
 */
export class AppVisualGridService {

  /**
   * @description 表格列
   * @private
   * @type {Array<any>}
   * @memberof AppVisualGridService
   */
  private columns: Array<any> = [];

  /**
   * @description 部件实例
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private controlInstance!: IPSDEGrid;

  /**
   * @description 代码表服务
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private codeListService!: any;

  /**
   * @description 应用上下文
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private context!: IParam;

  /**
   * @description 视图参数
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private viewParam!: IParam;

  /**
   * @description 代码表Map
   * @private
   * @type {Map<string,any>}
   * @memberof AppVisualGridService
   */
  private codeListMap: Map<string, any> = new Map();

  /**
   * @description 数据源
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private visualCtrlData: any;

  /**
   * @description lucky表格数据
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private luckyGridData: any;

  /**
   * @description 原始数据
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private basicData: Array<any> = [];

  /**
   * @description 表格区域
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private ctrlRange: any = {};

  /**
   * @description 表格配置参数
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private sheetConfig: any;

  /**
   * @description 分组模式
   * @private
   * @type {('AUTO' | 'CODELIST' | string)}
   * @memberof AppVisualGridService
   */
  private groupMode?: string | 'NONE' | 'AUTO' | 'CODELIST';

  /**
   * @description 分组属性
   * @private
   * @type {string}
   * @memberof AppVisualGridService
   */
  private groupField?: string;

  /**
   * @description 分组属性对应数据项名称
   * @private
   * @type {string}
   * @memberof AppVisualGridService
   */
  private groupDataItemName: string = '';

  /**
   * @description 分组代码表
   * @private
   * @type {*}
   * @memberof AppVisualGridService
   */
  private groupCodeList?: any;

  /**
   * @description 是否开启分组
   * @private
   * @type {boolean}
   * @memberof AppVisualGridService
   */
  private enableGroup: boolean = false;

  /**
   * @description 分组配置集合
   * @private
   * @type {Map<string, any>}
   * @memberof AppVisualGridService
   */
  private groupOptMap: Map<string, any> = new Map();

  /**
   * @description 列宽集合
   * @private
   * @type {Map<string, number>}
   * @memberof AppVisualGridService
   */
  private columnLenMap: Map<string, number> = new Map();

  /**
   * Creates an instance of AppVisualGridService.
   * @param {*} opt
   * @memberof AppVisualGridService
   */
  constructor(opt: any) {
    this.controlInstance = opt?.controlInstance;
    this.context = opt?.context;
    this.viewParam = opt?.viewParam;
    this.codeListService = opt?.codeListService;
  }

  /**
 * @description 获取表格区域
 * @return {*} 
 * @memberof AppVisualGridService
 */
  public getCtrlRange() {
    return this.ctrlRange;
  }

  /**
   * @description 设置表格配置参数
   * @param {*} userConfig
   * @memberof AppVisualGridService
   */
  public setSheetConfig(userConfig: any) {
    Object.assign(this.sheetConfig, userConfig);
  }

  /**
   * @description 获取表格配置参数
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public getSheetConfig() {
    return this.sheetConfig;
  }

  /**
   * @description 获取LuckyGrid数据
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public getLuckyGridData() {
    return this.luckyGridData;
  }

  /**
   * @description 获取数据源
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public getVisualCtrlData() {
    return this.visualCtrlData;
  }

  /**
   * @description 设置数据源
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public setVisualCtrlData(rowIndex: number, key: string, value: any) {
    this.visualCtrlData[rowIndex][key] = value;
  }

  /**
   * @description 初始化基础数据
   * @param {any[]} columnArray
   * @memberof AppVisualGridService
   */
  public initBasicData(columnArray: any[]) {
    if (columnArray && columnArray.length > 0) {
      columnArray.forEach((element: any) => {
        this.columns.push(this.controlInstance?.getPSDEGridColumns()?.find((item: any) => {
          return item.codeName === element;
        }))
      });
    }
    if (this.controlInstance.enableGroup) {
      this.groupMode = this.controlInstance.groupMode;
      this.groupField = this.controlInstance.getGroupPSAppDEField?.()?.codeName?.toLowerCase();
      this.groupDataItemName = (this.columns.find((column: IPSDEGridColumn) => {
        return (column as IPSDEGridFieldColumn).getPSAppDEField?.()?.codeName?.toLowerCase() == this.groupField;
      }) as IPSDEGridFieldColumn)?.dataItemName || '';
      if (this.groupMode == 'CODELIST') {
        this.groupCodeList = this.controlInstance.getGroupPSCodeList?.();
      }
      this.enableGroup = this.groupMode == 'NONE' || !Util.isExistAndNotEmpty(this.groupDataItemName) || (this.groupMode == 'CODELIST' && !this.groupCodeList) ? false : true;
    }
  }

  /**
   * @description 初始化虚拟表格
   * @param {*} position 定位信息
   * @param {*} data 表格数据
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public async initVisualCtrl(position: any, data: any = []) {
    this.visualCtrlData = data;
    this.initCtrlData(data);
    await this.initCodeListMap();
    return this.initVisualGrid(position);
  }

  /**
   * @description 初始化控件数据
   * @param {*} data
   * @memberof AppVisualGridService
   */
  public initCtrlData(data: any) {
    if (this.columns && this.columns.length > 0) {
      this.basicData = [];
      // 表格头部数据
      let headerArray: Array<any> = [];
      this.columns.forEach((column: IPSDEGridColumn) => {
        const tempData = {
          codeName: column.codeName,
          value: column.caption,
          width: column.width,
          isHeader: true,
          model: column,
          hidden: false
        }
        this.columnLenMap.set(column.codeName, column.width);
        headerArray.push(tempData);
      })
      this.basicData.push(headerArray);
      // 表格主体数据
      if (this.enableGroup) {
        this.initGroupData(data);
      } else {
        if (data && data.length > 0) {
          data.forEach((item: any) => {
            const rowArray: Array<any> = [];
            this.columns.forEach((column: IPSDEGridColumn) => {
              const tempData = {
                codeName: column.codeName,
                value: item[column.dataItemName],
                width: column.width,
                isHeader: false,
                model: column,
                enableRowEdit: column.enableRowEdit,
                hidden: false,
                originalData: item
              }
              if (column.enableRowEdit) {
                const editColumn = this.controlInstance.getPSDEGridEditItems()?.find((editItem: IPSDEGridEditItem) => {
                  return editItem.codeName === column.codeName;
                })
                Object.assign(tempData, { editColumn: editColumn })
              }
              rowArray.push(tempData);
            })
            this.basicData.push(rowArray);
          });
        }
      }
    }
  }


  /**
   * @description 初始化分组数据
   * @memberof AppVisualGridService
   */
  public initGroupData(data: any[]) {
    if (data && data.length > 0) {
      const tempData: any[] = Util.arraySort(data, this.groupDataItemName);
      this.initGroupOptMap(tempData);
      tempData.forEach((item: any) => {
        const rowArray: Array<any> = [];
        this.columns.forEach((column: IPSDEGridColumn) => {
          const tempData = {
            codeName: column.codeName,
            value: item[column.dataItemName],
            width: column.width,
            isHeader: false,
            model: column,
            enableRowEdit: column.enableRowEdit,
            hidden: false,
            originalData: item
          }
          if (column.enableRowEdit) {
            const editColumn = this.controlInstance.getPSDEGridEditItems()?.find((editItem: IPSDEGridEditItem) => {
              return editItem.codeName === column.codeName;
            })
            Object.assign(tempData, { editColumn: editColumn })
          }
          rowArray.push(tempData);
        })
        this.basicData.push(rowArray);
      })
    }
  }

  /**
   * @description 初始化分组配置
   * @param {any[]} data
   * @memberof AppVisualGridService
   */
  public initGroupOptMap(data: any[]) {
    //  分组列是第几列
    const colIndex = this.columns.findIndex((column: IPSDEGridColumn) => {
      return (column as IPSDEGridFieldColumn).getPSAppDEField?.()?.codeName?.toLowerCase() == this.groupField;
    });
    data.forEach((item: any, row: number) => {
      const key = item[this.groupDataItemName];
      const value = this.groupOptMap.get(key);
      if (value && value.count != undefined) {
        this.groupOptMap.set(key, {
          count: ++value.count,
          rowIndex: value.rowIndex,
          colIndex: colIndex
        })
      } else {
        this.groupOptMap.set(key, {
          count: 1,
          rowIndex: row + 1,
          colIndex: colIndex
        })
      }
    })
  }

  /**
   * @description 初始化代码表
   * @memberof AppVisualGridService
   */
  public async initCodeListMap() {
    if (this.columns && this.columns.length > 0) {
      for (const column of this.columns) {
        const codeList: IPSAppCodeList | null = column.getPSAppCodeList?.();
        if (codeList) {
          const items = await this.getCodeListByTag(codeList);
          this.codeListMap.set(codeList.codeName, items);
        }
      }
    }
  }

  /**
   * @description 获取指定代码表
   * @param {IPSAppCodeList} codeList 代码表对象
   * @memberof AppVisualGridService
   */
  public async getCodeListByTag(codeList: IPSAppCodeList) {
    if (this.codeListService && codeList) {
      const queryData = { tag: codeList?.codeName, type: codeList?.codeListType, data: codeList, context: this.context, viewparam: this.viewParam };
      return await this.codeListService.getDataItems(queryData);
    }
  }

  /**
   * @description 初始化LuckyGrid数据
   * @param {*} position 位置信息
   * @memberof AppGridService
   */
  public initVisualGrid(position: any, isInit: boolean = true) {
    this.initLuckyGridData(this.basicData, position);
    this.initCtrlRange(position, isInit);
    this.initSheetConfig(this.visualCtrlData, position);
    return { luckyGridData: this.luckyGridData, position: this.ctrlRange, sheetConfig: this.sheetConfig };
  }

  /**
   * @description 设置LuckyGrid数据
   * @param {Array<any>} basicData 源数据
   * @param {*} position 位置信息
   * @memberof AppVisualGridService
   */
  public initLuckyGridData(basicData: Array<any>, position: any) {
    if (basicData && basicData.length > 0) {
      this.luckyGridData = [];
      if (this.enableGroup) {
        this.initLuckyGridDataForGroup(basicData, position);
      } else {
        basicData.forEach((items: any, row: number) => {
          if (items && items.length > 0) {
            items.forEach((element: any, col: number) => {
              let cellData = this.getColumnData(position, element, row, col);
              this.luckyGridData.push(cellData);
            });
          }
        })
      }
    }
  }

  /**
   * @description 设置LuckyGrid数据（分组）
   * @param {Array<any>} basicData 源数据
   * @param {*} position 位置信息
   * @memberof AppVisualGridService
   */
  public initLuckyGridDataForGroup(basicData: Array<any>, position: any) {
    //  分组列是第几列 (当 this.enableGroup 为 true 时则表示分组列必定绘制)
    const colIndex = this.columns.findIndex((column: IPSDEGridColumn) => {
      return (column as IPSDEGridFieldColumn).getPSAppDEField?.()?.codeName.toLowerCase() == this.groupField;
    });
    basicData.forEach((items: any, row: number) => {
      if (items && items.length > 0) {
        //  合并单元格 主单元格
        items.forEach((element: any, col: number) => {
          let cellData: any = null;
          const key = element.originalData?.[this.groupDataItemName];
          // 是否是分组列下的单元格
          const isGroupColumn: boolean = col == colIndex;
          if (isGroupColumn && !element.isHeader) {
            const value = this.groupOptMap.get(key);
            cellData = this.getColumnData(position, element, row, col);
            //  是否是起始分组行
            if (value.rowIndex == row) {
              Object.assign(cellData.options, {
                "mc": {
                  "r": position.startRow + value.rowIndex,
                  "c": position.startCol + value.colIndex,
                  "rs": value.count,
                  "cs": 1
                }
              })
            } else {
              Object.assign(cellData.options, {
                "mc": {
                  "r": position.startRow + value.rowIndex,
                  "c": position.startCol + value.colIndex,
                }
              })
            }
          } else {
            cellData = this.getColumnData(position, element, row, col);
          }
          this.luckyGridData.push(cellData);
        });
      }
    })
  }

  /**
   * @description 初始化部件数据
   * @param {*} position 定位
   * @param {boolean} [isInit=true] 是否初始化
   * @memberof AppVisualGridService
   */
  public initCtrlRange(position: any, isInit: boolean = true) {
    let left = 0,
      top = 0,
      width = 0,
      height = 0,
      row = position.startRow,
      col = position.startCol;
    if (position.startCol) {
      for (let i = 0; i < position.startCol; i++) {
        const result = SheetUtil.getColumnWidth([i]);
        left += result[i] + 1;
      }
    }
    if (position.startRow) {
      for (let i = 0; i < position.startRow; i++) {
        const result = SheetUtil.getRowHeight([i]);
        top += result[i] + 1;
      }
    }
    // 初始化
    if (isInit) {
      if (this.columns && this.columns.length > 0) {
        this.columns.forEach((column: any) => {
          width += column.width + 1;
          col += 1;
        });
      }
      // 表头高度
      height += SheetUtil.getDefaultRowHeight() + 1;
      row += 1;
      // 内容区高度
      if (this.visualCtrlData && this.visualCtrlData.length > 0) {
        this.visualCtrlData.forEach((item: any) => {
          height += SheetUtil.getDefaultRowHeight() + 1;
          row += 1;
        })
      }
    } else {
      // 已完成初始化
      if (this.columns && this.columns.length > 0) {
        this.columns.forEach((column: any, i: number) => {
          width += ((this.columnLenMap.get(column.codeName) || column.width) + 1);
          col += 1;
        });
      }
      // 表头高度
      height += SheetUtil.getRowHeight([position.startRow])[position.startRow] + 1;
      row += 1;
      // 内容区高度
      if (this.visualCtrlData && this.visualCtrlData.length > 0) {
        this.visualCtrlData.forEach((item: any, i: number) => {
          height += SheetUtil.getRowHeight([position.startRow + i])[position.startRow + i] + 1;
          row += 1;
        })
      }
    }
    this.ctrlRange = { left, top, width, height, row, col, startRow: position.startRow, startCol: position.startCol };
  }

  /**
   * @description 初始化列数据模型
   * @param {*} position 定位
   * @param {*} element 列基础数据
   * @param {number} row 行
   * @param {number} col 列
   * @memberof AppVisualGridService
   */
  public getColumnData(position: any, element: any, row: number, col: number) {
    let cellData = {
      "r": position.startRow + row,
      "c": position.startCol + col,
      "options": {
        "ct": {
          "fa": "General",
          "t": "g"
        },
        "v": element.value,
        "m": this.getCellMonitor(element, this.codeListMap)
      }
    }
    if (!element.isHeader) {
      // 链接视图
      if (element.model?.enableLinkView) {
        Object.assign(cellData.options, {
          fc: "#0000FF",
          link: true,
          codeName: element.codeName,
          originalData: JSON.stringify(element.originalData)
        })
      }
      if (element.editColumn && element.enableRowEdit) {
        Object.assign(cellData.options, {
          enableRowEdit: element.enableRowEdit,
          editColumn: element.editColumn,
          codeName: element.codeName,
          originalData: element.originalData,
          bg: '#dfda94'
        })
      }
    }
    return cellData;
  }

  /**
   * @description 计算表格单元格显示值
   * @param {*} cellData 单元格原生数据
   * @param {Map<string, any>} codeListMap 代码表集合
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public getCellMonitor(cellData: any, codeListMap: Map<string, any>) {
    const { codeName, value, width, isHeader, model, hidden, originalData } = cellData;
    if (isHeader) {
      return value;
    } else {
      const { cLConvertMode, enableLinkView, dataItemName, userTag } = model;
      const codeList: IPSAppCodeList | null = model.getPSAppCodeList?.();
      if (codeList) {
        //  代码表
        const codeListItems = codeListMap.get(codeList.codeName);
        if (codeListItems && codeListItems.length > 0) {
          const item = codeListItems.find((ele: any) => {
            return ele.value === value;
          })
          return item && item.text ? item.text : value;
        } else {
          return value;
        }
      } else if (enableLinkView && model.getLinkPSAppView()) {
        // 链接视图显示
        return value;
      } else if (userTag) {
        // 地址栏
        if (Object.is(userTag, 'ADDRESSPICKUP')) {
          if (Util.isEmpty(value)) {
            return '';
          } else {
            let text: string = '';
            JSON.parse(value).forEach((item: any, index: number) => {
              text += index === 0 ? item.srfmajortext : ',' + item.srfmajortext;
            });
            return text;
          }
        }
      } else {
        //常规显示
        return value;
      }
    }
  }

  /**
   * @description 判断当前激活项控件
   * @param {*} position
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public checkSelectedCtrl(position: any, curPosition: any) {
    if (curPosition) {
      const tempPosition = {
        start_r: curPosition.top,
        start_c: curPosition.left,
        end_r: curPosition.top + curPosition.height,
        end_c: curPosition.left + curPosition.width
      };
      if ((position.start_r >= tempPosition.start_r) &&
        (position.start_c >= tempPosition.start_c) &&
        (position.end_r <= tempPosition.end_r) &&
        (position.end_c <= tempPosition.end_c)) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }

  /**
   * @description 计算位置
   * @param {number} x 横坐标
   * @param {number} y 纵坐标
   * @param {any[]} dataColumns 工作表列数据
   * @param {any[]} dataRows 工作表行数据
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public compPosition(x: number, y: number) {
    const curSheet = SheetUtil.getSheet();
    const dataColumns = curSheet.visibledatacolumn;
    const dataRows = curSheet.visibledatarow;
    const compResult = { startCol: 0, startRow: 0 };
    for (let i = 0; i < dataColumns.length; i++) {
      if (x >= dataColumns[i] && x < dataColumns[i + 1]) {
        Object.assign(compResult, { startCol: i + 2 });
        break;
      }
    }
    for (let i = 0; i < dataRows.length; i++) {
      if (y >= dataRows[i] && y < dataRows[i + 1]) {
        Object.assign(compResult, { startRow: i + 2 });
        break;
      }
    }
    return Object.assign(this.ctrlRange, compResult);
  }

  /**
   * @description 设置表格sheet配置参数
   * @param {*} data 表格数据
   * @param {*} position 位置信息
   * @memberof AppVisualGridService
   */
  public initSheetConfig(data: any, position: any): any {
    const coLenConfig = {};
    const borderInfoConfig = [
      {
        "rangeType": "range",
        "borderType": "border-all",
        "style": "1",
        "color": "#909399",
        "range": [{
          "row": [position.startRow, data.length + position.startRow],
          "column": [position.startCol, this.columns.length + position.startCol - 1]
        }]
      }
    ];
    const mergeConfig: any = {};
    if (this.columns && this.columns.length > 0) {
      for (let i = 0; i < this.columns.length; i++) {
        const column = this.columns[i];
        Object.assign(coLenConfig, { [i + position.startCol]: this.columnLenMap.get(column.codeName) || column.width });
      }
    }
    if (this.enableGroup && this.groupOptMap.size > 0) {
      this.groupOptMap.forEach((value: any, key: string) => {
        const { rowIndex, colIndex, count } = value;
        Object.assign(mergeConfig, {
          [`${position.startRow + rowIndex}_${position.startCol + colIndex}`]: {
            "r": position.startRow + rowIndex,
            "c": position.startCol + colIndex,
            "rs": count,
            "cs": 1
          }
        })
      })
    }
    this.sheetConfig = {
      config: {
        columnlen: coLenConfig,
        borderInfo: borderInfoConfig,
        merge: mergeConfig
      }
    };
  }

  /**
   * @description 更新列宽
   * @param {*} position 定位
   * @param {*} columnLen 列宽
   * @return {*} 
   * @memberof AppVisualGridService
   */
  public updateColumnLen(position: any, columnLen: any) {
    if (!columnLen || Object.keys(columnLen).length == 0) {
      return;
    }
    this.columns.forEach((column: IPSDEGridColumn, index: number) => {
      this.columnLenMap.set(column.codeName, columnLen[index + position.startCol]);
    });
  }

  /**
   * @description 删除选中区域数据
   * @param {*} position 区域信息
   * @memberof AppVisualGridService
   */
  public clearSelectedRange(position: any) {
    // 清空所有编辑项
    SheetUtil.getElement('.app-visual-ctrl-item').remove();
    // 清空单元格值
    for (let i = position.startRow; i < position.row + 1; i++) {
      for (let j = position.startCol; j < position.col + 1; j++) {
        SheetUtil.clearCell(i, j);
      }
    }
    // 清空配置
    SheetUtil.setConfig({
      borderInfo: {},
      merge: {}
    });
  }
}